package org.shiki.hrm.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import javax.sql.DataSource;
import java.util.Arrays;

/**
 * 授权配置
 */
@EnableAuthorizationServer
@Configuration
public class HrmAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
	@Autowired
	private DataSource dataSource;

	@Autowired
	private PasswordEncoder passwordEncoder;


	/**
	 * 配置放行路径
	 * @param security
	 * @throws Exception
	 */
	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
		security
				//对应/oauth/check_token ，路径公开
				.checkTokenAccess("permitAll()")
				//允许客户端进行表单身份验证,使用表单认证申请令牌
				.allowFormAuthenticationForClients();
	}

	/**
	 * 配置客户端详情
	 * @param clients
	 * @throws Exception
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		JdbcClientDetailsService clientDetailsService = clientDetailsService();
		clients.withClientDetails(clientDetailsService);
	}

	private JdbcClientDetailsService clientDetailsService() {
		JdbcClientDetailsService service = new JdbcClientDetailsService(dataSource);
		service.setPasswordEncoder(passwordEncoder);
		return service;
	}

	@Autowired
	private AuthenticationManager authenticationManager;

	/**
	 * 配置token的管理和存储方式
	 * @param endpoints
	 * @throws Exception
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints
				//1.密码授权模式需要
				.authenticationManager(authenticationManager)
				//2.授权码模式服务
				.authorizationCodeServices(authorCodeServices())
				//3.配置令牌管理服务
				.tokenServices(tokenService())
				// 允许post方式请求
				.allowedTokenEndpointRequestMethods(HttpMethod.POST, HttpMethod.GET);
	}

	@Bean
	public AuthorizationServerTokenServices tokenService() {
		DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
		// 设置token和客户端的关系
		defaultTokenServices.setClientDetailsService(clientDetailsService());
		defaultTokenServices.setSupportRefreshToken(true);
		// 设置token存储方式等
		defaultTokenServices.setTokenStore(tokenStore());
		// 设置token增强
		TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
		tokenEnhancerChain.setTokenEnhancers(Arrays.asList(getJwtTokenConvert()));
		defaultTokenServices.setTokenEnhancer(tokenEnhancerChain);
		return defaultTokenServices;
	}

	@Bean
	public TokenStore tokenStore() {
//		return new InMemoryTokenStore();
		JwtTokenStore jwtTokenStore = new JwtTokenStore(getJwtTokenConvert());
		return jwtTokenStore;
	}

	private final String KEY  = "gzjkljgjij";

	@Bean
	public JwtAccessTokenConverter getJwtTokenConvert() {
		JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
		// 设置签名密钥
		jwtAccessTokenConverter.setSigningKey(KEY);
		return jwtAccessTokenConverter;
	}

	@Bean
	public AuthorizationCodeServices authorCodeServices() {
		JdbcAuthorizationCodeServices jdbcAuthorizationCodeServices = new JdbcAuthorizationCodeServices(dataSource);
		return jdbcAuthorizationCodeServices;
	}

}
